package com.skivingcloud.admin.security;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.skivingcloud.admin.sys.service.SysCaptchaService;
import com.skivingcloud.validation.exceptions.ValidateCaptchaException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.util.Map;

import static com.skivingcloud.admin.security.MyAuthenticationHandler.APPLICATION_JSON_CHARSET_UTF_8;


/**
 * @author hushouquan
 */
@Component
public class MyLoginFilter extends UsernamePasswordAuthenticationFilter{
    private final ObjectMapper objectMapper = new ObjectMapper();
    private final SysCaptchaService sysCaptchaService;
    
    public MyLoginFilter(AuthenticationManager authenticationManager,
                         MyAuthenticationHandler authenticationHandler,
                         MyRememberMeServices rememberMeServices, SysCaptchaService sysCaptchaService){
        super(authenticationManager);
        this.sysCaptchaService = sysCaptchaService;
        setAuthenticationFailureHandler(authenticationHandler);
        setAuthenticationSuccessHandler(authenticationHandler);
        //rememberMe
        setRememberMeServices(rememberMeServices);
        //登陆使用的路径
        setFilterProcessesUrl("/sys/auth/login");
    }
    
    private static boolean isContentTypeJson(HttpServletRequest request) {
        final String contentType = request.getContentType().replace(" ", "");
        return APPLICATION_JSON_CHARSET_UTF_8.equalsIgnoreCase(contentType) || MimeTypeUtils.APPLICATION_JSON_VALUE.equalsIgnoreCase(contentType);
    }
    
    /**
     * 登录验证会走这里
     * @param request 参数
     * @param response 返回
     * @return 验证结果
     * @throws AuthenticationException 验证异常
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException{
        
        if (!HttpMethod.POST.name().equalsIgnoreCase(request.getMethod())) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }
        String username;
        String password;
        String captcha;
        String uuid;
        String rememberMe;
        if (isContentTypeJson(request)) {
            try {
                Map<String, String> map = objectMapper.readValue(request.getInputStream(), new TypeReference<>() {
                });
                username = map.get(getUsernameParameter());
                password = map.get(getPasswordParameter());
                captcha = map.get("captcha").trim();
                uuid = map.get("uuid").trim();
                rememberMe = map.get(MyRememberMeServices.REMEMBER_ME_KEY);
            } catch (IOException e) {
                throw new RuntimeException("参数格式不正确");
            }
        } else {
            username = obtainUsername(request);
            password = obtainPassword(request);
            captcha = request.getParameter("captcha").trim();
            uuid = request.getParameter("uuid").trim();
            rememberMe = request.getParameter(MyRememberMeServices.REMEMBER_ME_KEY);
        }
        boolean validateCaptcha = sysCaptchaService.validate(uuid, captcha);
        if(!validateCaptcha){
            throw new ValidateCaptchaException("验证码不正确");
        }
        //将 rememberMe 状态存入 attr中
        if (!ObjectUtils.isEmpty(rememberMe)) {
            request.setAttribute(MyRememberMeServices.REMEMBER_ME_KEY, rememberMe);
        }
        
        username = (username != null) ? username.trim() : "";
        password = (password != null) ? password : "";
        // System.out.println("密码:" + passwordEncoder.encode(password));
        UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username, password);
        // Allow subclasses to set the "details" property
        setDetails(request, authRequest);
        
        return this.getAuthenticationManager().authenticate(authRequest);
    }
}
